package java0415;

import java.util.HashMap;
import java.util.Map;

class Node {
    int val;
    Node next;
    Node random;

    public Node(int val) {
        this.val = val;
    }
}

class ListNode {
    int val;
    ListNode next;

    public ListNode(int val) {
        this.val = val;
    }
}

public class Solution {

    // 复制带随机指针的链表
    // 给你一个长度为 n 的链表，每个节点包含一个额外增加的随机指针 random ，该指针可以指向链表中的任何节点或空节点。
    //构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成，其中每个新节点的值都设为其对应的原节点的值。新节点的 next 指针和 random 指针也都应指向复制链表中的新节点，并使原链表和复制链表中的这些指针能够表示相同的链表状态。复制链表中的指针都不应指向原链表中的节点 。
    //例如，如果原链表中有 X 和 Y 两个节点，其中 X.random --> Y 。那么在复制链表中对应的两个节点 x 和 y ，同样有 x.random --> y 。
    //返回复制链表的头节点
    //用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示：
    //val：一个表示 Node.val 的整数。
    //random_index：随机指针指向的节点索引（范围从 0 到 n-1）；如果不指向任何节点，则为  null 。
    //你的代码 只 接受原链表的头节点 head 作为传入参数。
    public Node copyRandomList(Node head) {
        if (head == null) {
            return null;
        }
        Map<Node, Node> map = new HashMap<>();
        Node cur = head;
        for (; cur != null; cur = cur.next) {
            map.put(cur, new Node(cur.val));
        }
        for (cur = head; cur != null; cur = cur.next) {
            map.get(cur).next = map.get(cur.next);
            map.get(cur).random = map.get(cur.random);
        }
        return map.get(head);
    }

    // 回文链表
    // 请判断一个链表是否为回文链表。
    public boolean isPalindrome(ListNode head) {
        if (head == null || head.next == null) {
            return true;
        }
        int length = length(head);
        ListNode cur = head;
        for (int i = 0; i < length / 2; i++) {
            cur = cur.next;
        }
        ListNode newCur = reversal(cur);
        cur = head;
        while (cur != null && newCur != null) {
            if (cur.val != newCur.val) {
                return false;
            }
            cur = cur.next;
            newCur = newCur.next;
        }
        return true;
    }

    private ListNode reversal(ListNode cur) {
        if (cur == null) {
            return null;
        }
        if (cur.next == null) {
            return cur;
        }
        ListNode pre = null;
        ListNode next = cur.next;
        while (true) {
            cur.next = pre;
            pre = cur;
            cur = next;
            if (next != null) {
                next = next.next;
            }else {
                break;
            }
        }
        return pre;
    }

    // 合并两个有序链表
    // 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if (l1 == null && l2 == null) {
            return null;
        }
        if (l1 == null) {
            return l2;
        }
        if (l2 == null) {
            return l1;
        }
        ListNode newList = new ListNode(0);
        ListNode cur = newList;
        while (l1 != null && l2 != null) {
            if (l1.val < l2.val) {
                cur.next = l1;
                l1 = l1.next;
            }else {
                cur.next = l2;
                l2 = l2.next;
            }
            cur = cur.next;
        }
        if (l1 == null) {
            cur.next = l2;
        }else {
            cur.next = l1;
        }
        return newList.next;
    }

    public int length(ListNode head) {
        ListNode cur = head;
        int ret = 0;
        for (; cur != null; cur = cur.next) {
            ret++;
        }
        return ret;
    }

    // 旋转链表
    // 给你一个链表的头节点 head ，旋转链表，将链表每个节点向右移动 k 个位置。
    public ListNode rotateRight(ListNode head, int k) {
        if (head == null) {
            return null;
        }
        if (head.next == null) {
            return head;
        }
        int length = length(head);
        int move = k % length;
        if (move == 0) {
            return head;
        }
        int pos = length - move;
        ListNode cur = head;
        for (int i = 1; i < pos; i++) {
            cur = cur.next;
        }
        ListNode ret = cur.next;
        cur.next = null;
        cur = ret;
        while (cur != null && cur.next != null) {
            cur = cur.next;
        }
        cur.next = head;
        return ret;
    }
}
